# -*- coding:utf-8 -*-
#! python3

# FaceCat-Python
#Shanghai JuanJuanMao Information Technology Co., Ltd 

import requests
from requests.adapters import HTTPAdapter
from facecat_objc import *

#pip3 uninstall pyobjc
#pip3 install pyobjc

#视图的鼠标按下方法
#view 视图
#mp 坐标
#buttons 按钮 0未按下 1左键 2右键
#clicks 点击次数
#delta 滚轮值
def onMouseDown(view, mp, buttons, clicks, delta):
	if view.viewType == "chart":
		if len(view.datas) == 0:
			return
		if len(view.addingPlot) > 0:
			addPlotDefault(view, True, mp, False, mp)
			view.addingPlot = ""
			invalidateView(chart)
		else:
			touchDownChart(view, True, mp, False, mp)
			invalidateView(chart)
	else:
		onMouseDownDefault(view, mp, buttons, clicks, delta)

#视图的鼠标点击方法
#view 视图
#mp 坐标
#buttons 按钮 0未按下 1左键 2右键
#clicks 点击次数
#delta 滚轮值
def onClick(view, firstTouch, firstPoint, secondTouch, secondPoint, clicks):
	onClickDefault(view, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
	global chart
	if len(view.viewName) > 0:
		if view.viewName.find("Indicator_") == 0:
			if view.text == "BOLL" or view.text == "MA":
				chart.mainIndicator = view.text
			else:
				chart.showIndicator = view.text
			calcChartIndicator(chart)
			invalidateView(chart)
		elif view.viewName.find("Plot_") == 0:
			chart.addingPlot = view.viewName[5:]

#请求历史数据
def queryHistoryData():
	global chart
	try:
		url = "https://web.ifzq.gtimg.cn/appstock/app/fqkline/get?_var=kline_dayqfq&param=sh601857,day,,,320,qfq&r=0.9860043111257255"
		s = requests.Session()
		s.mount('http://', HTTPAdapter(max_retries=3))
		response = s.get(url)
		result = response.text
		dataList = []
		datas = result.split("[")
		for i in range(0, len(datas)):
			subDatas = datas[i].split(",")
			if len(subDatas) == 7:
				data = SecurityData()
				dateStr = subDatas[0].replace("'", "").replace("\"", "")
				date_obj = datetime.datetime.strptime(dateStr, "%Y-%m-%d")
				data.close = float(subDatas[2].replace("'", "").replace("\"", ""))
				data.high = float(subDatas[3].replace("'", "").replace("\"", ""))
				data.low = float(subDatas[4].replace("'", "").replace("\"", ""))
				data.open = float(subDatas[1].replace("'", "").replace("\"", ""))
				data.volume = float(subDatas[5].replace("'", "").replace("\"", "").replace("]", ""))
				data.date = time.mktime(date_obj.timetuple())
				dataList.append(data)
		chart.datas = dataList
		chart.text = "601857 中国石油 日线"
		maxVisibleRecord = getChartMaxVisibleCount(chart, chart.hScalePixel, getChartWorkAreaWidth(chart))
		chart.lastVisibleIndex = len(chart.datas) - 1
		if maxVisibleRecord > len(chart.datas):
			chart.firstVisibleIndex = 0
		else:
			chart.firstVisibleIndex = chart.lastVisibleIndex - maxVisibleRecord + 1
		resetChartVisibleRecord(chart)
		checkChartLastVisibleIndex(chart)
		calcChartIndicator(chart)
		invalidateView(chart)
	except requests.exceptions.RequestException as e:
			print(e)

#黑色风格
def toBlackChart():
	global chart
	chart.paint.defaultUIStyle = "dark"
	chart.backColor = "rgb(0,0,0)"
	chart.borderColor = "none"
	chart.textColor = "rgb(255,255,255)"
	chart.scaleColor = "rgb(75,75,75)"
	chart.crossTipColor = "rgb(50,50,50)"
	chart.crossLineColor = "rgb(100,100,100)"
	chart.gridColor = "rgb(50,50,50)"
	chart.trendColor = "rgb(255,255,255)"
	chart.indicatorColors = []
	chart.indicatorColors.append("rgb(255,255,255)")
	chart.indicatorColors.append("rgb(255,255,0)")
	chart.indicatorColors.append("rgb(255,0,255)")
	chart.indicatorColors.append("rgb(255,0,0)")
	chart.indicatorColors.append("rgb(0,255,255)")
	chart.indicatorColors.append("rgb(0,255,0)")
	chart.indicatorColors.append("rgb(255,255,0)")
	chart.indicatorColors.append("rgb(255,255,255)")
	for i in range(0, len(chart.plots)):
		plot = chart.plots[i]
		plot.lineColor = "rgb(255,255,255)"
		plot.pointColor = "rgba(255,255,255,125)"

#绘制横轴刻度的自定义方法
#chart:图表
#paint:绘图对象
#clipRect:裁剪区域
#该逻辑仅针对日K线
def drawChartHScale(chart, paint, clipRect):
	#判断数据是否为空
	if chart.datas != None and len(chart.datas) > 0 and chart.hScaleHeight > 0:
		drawLeft = chart.leftVScaleWidth #左侧起画点
		i = chart.firstVisibleIndex #开始索引
		lastYear = 0 #缓存年份，用于判断是否换年
		drawYearsCache = [] #实际绘制到图形上的年份文字
		lastTextRight = 0 #上个文字的右侧
		timeCache = [] #保存日期的缓存
		yearTextLeftCache = [] #绘制年文字的左侧位置缓存
		yearTextRightCache = [] #绘制年文字的右侧位置缓存
		textPadding = 5 #两个文字之间的最小间隔
		#逐步递增索引，先绘制年
		while i <= chart.lastVisibleIndex:
			dateObj = time.localtime(chart.datas[i].date) #将时间戳转换为time，并缓存到集合中
			timeCache.append(dateObj)
			year = dateObj.tm_year #从结构中获取年份			
			x = getChartX(chart, i) #获取索引对应的位置
			#判断是否换年，以及是否在绘图区间内
			if year != lastYear and x >= drawLeft and x < chart.size.cx - chart.rightVScaleWidth:
				month = dateObj.tm_mon #获取月的结构
				xText = str(year) #拼接要绘制的文字
				if month < 10:
					xText = xText + "/0" + str(month) #如果小于10月要补0
				else:
					xText = xText + "/" + str(month) #大于等于10月不用补0
				tSize = paint.textSize(xText, chart.font) #计算要绘制文字的大小
				paint.drawLine(chart.gridColor, 1, 0, x, chart.size.cy - chart.hScaleHeight, x, chart.size.cy - chart.hScaleHeight + 8) #绘制刻度线
				#判断是否和上个文字重影
				if x - tSize.cx / 2 > lastTextRight + textPadding:
					paint.drawText(xText, chart.hScaleTextColor, "Default,12", x - tSize.cx / 2, chart.size.cy - chart.hScaleHeight + 8  - tSize.cy / 2 + 7) #绘制文字
					yearTextLeftCache.append(x - tSize.cx / 2) #将年文字的左侧位置缓存
					yearTextRightCache.append(x + tSize.cx / 2) #将年文字的右侧位置缓存
					drawYearsCache.append(year) #缓存要绘制的年
					lastTextRight = x + tSize.cx / 2 #缓存上个文字的右侧位置
				lastYear = year #记录上次绘制的年份
			i = i + 1	#索引累加	
		#绘制月份
		for m in range(0, len(drawYearsCache)):
			cacheYear = drawYearsCache[m] #从缓存中获取年份
			lastMonth = 0 #缓存月份，用于判断是否换月
			i = chart.firstVisibleIndex #重置开始索引
			lastTextRight = 0 #重置上个文字的右侧
			#逐步递增索引
			while i <= chart.lastVisibleIndex:
				dateObj = timeCache[i - chart.firstVisibleIndex] #从缓存中获取time
				year = dateObj.tm_year #从结构中获取年份
				#判断是否同一年	
				if cacheYear == year:
					month = dateObj.tm_mon #从结构中获取月份
					x = getChartX(chart, i)
					#判断是否换月，以及是否在绘图区间内
					if lastMonth != month and x >= drawLeft and x < chart.size.cx - chart.rightVScaleWidth:			
						xText = str(month) #获取绘制的月份文字
						tSize = paint.textSize(xText, chart.font) #计算要绘制文字的大小
						#判断是否和上个文字重影
						if x - tSize.cx / 2 > lastTextRight + textPadding:
							#判断是否和年的文字重影
							if (x - tSize.cx / 2 > yearTextRightCache[m] + textPadding) and ((m == len(drawYearsCache) - 1) or (m < len(drawYearsCache) - 1 and x + tSize.cx / 2 < yearTextLeftCache[m + 1] - textPadding)):
								paint.drawLine(chart.gridColor, 1, 0, x, chart.size.cy - chart.hScaleHeight, x, chart.size.cy - chart.hScaleHeight + 6) #绘制刻度
								paint.drawText(xText, chart.hScaleTextColor, "Default,12", x - tSize.cx / 2, chart.size.cy - chart.hScaleHeight + 8  - tSize.cy / 2 + 7) #绘制文字
								lastTextRight = x + tSize.cx / 2 #缓存上个文字的右侧位置
						lastMonth = month #记录上次绘制的月份
				elif cacheYear < year:
					break #超过区间，退出循环
				i = i + 1	#索引累加

gPaint = FCPaint() #创建绘图对象
gPaint.defaultUIStyle = "dark"
gPaint.onMouseDown = onMouseDown 
gPaint.onClick = onClick
gPaint.onPaintChartHScale = drawChartHScale
chart = None

#加载示例
def loadUI():
	global chart
	global gPaint
	xml = """<?xml version="1.0" encoding="utf-8"?>
<html xmlns="facecat">
	<body>
	<div type="splitlayout" layoutstyle="toptobottom" bordercolor="none" dock="fill" size="400,400" candragsplitter="true" splitterposition="25,1">
		<div type="layout" backcolor="none" bordercolor="none">
		<select name="cbIndicator" selectedindex="0" size="80,25">
			<option text="MA" name="Indicator_MA" />
			<option text="BOLL" name="Indicator_BOLL" />
			<option text="MACD" name="Indicator_MACD" />
			<option text="KDJ" name="Indicator_KDJ" />
			<option text="BIAS" name="Indicator_BIAS" />
			<option text="BBI" name="Indicator_BBI" />
			<option text="RSI" name="Indicator_RSI" />
			<option text="ROC" name="Indicator_ROC" />
			<option text="WR" name="Indicator_WR" />
			<option text="DMA" name="Indicator_DMA" />
			<option text="TRIX" name="Indicator_TRIX" />
			<option text="CCI" name="Indicator_CCI" />
		</select>
		<select name="cbPlot" selectedindex="0" size="100,25">
			<option text="直线" name="Plot_Line" />
			<option text="线段" name="Plot_Segment" />
			<option text="射线" name="Plot_Ray" />
			<option text="三角形" name="Plot_Triangle" />
			<option text="矩形" name="Plot_Rect" />
			<option text="圆" name="Plot_Cycle" />
			<option text="外接圆" name="Plot_CircumCycle" />
			<option text="椭圆" name="Plot_Ellipse" />
			<option text="角度线" name="Plot_AngleLine" />
			<option text="线性回归" name="Plot_LRLine" />
			<option text="线性回归通道" name="Plot_LRChannel" />
			<option text="对称三角形" name="Plot_SymmetricTriangle" />
			<option text="线性回归带" name="Plot_LRBand" />
			<option text="平行四边形" name="Plot_ParalleGram" />
			<option text="速阻线" name="Plot_SpeedResist" />
			<option text="斐波扇面" name="Plot_FiboFanline" />
			<option text="斐波周期线" name="Plot_FiboTimezone" />
			<option text="百分比线" name="Plot_Percent" />
			<option text="箱型线" name="Plot_BoxLine" />
			<option text="泰龙水平线" name="Plot_TironeLevels" />
			<option text="四等分线" name="Plot_QuadrantLines" />
			<option text="平行线" name="Plot_Parallel" />
			<option text="黄金分割线" name="Plot_GoldenRatio" />
			<option text="箭头线段" name="Plot_ArrowSegment" />
		</select>
		</div>
		<chart size="200,200" name="Chart" text="Chart" dock="Fill"/>
	</div>
	</body>
</html>
	"""
	renderFaceCat(gPaint, xml)
	chart = findViewByName("Chart", gPaint.views)
	chart.leftVScaleWidth = 70
	chart.rightVScaleWidth = 70
	chart.vScaleDistance = 35
	chart.hScalePixel = 11
	chart.hScaleHeight = 30
	chart.candlePaddingTop = 30
	chart.candlePaddingBottom = 20
	chart.volPaddingTop = 20
	chart.volPaddingBottom = 0
	chart.indPaddingTop = 20
	chart.indPaddingBottom = 0
	chart.vScaleDistance = 35
	chart.dock = "fill"
	chart.mainIndicator = "BOLL"
	chart.showIndicator = "BIAS"
	chart.allowDragChartDiv = True
	toBlackChart()
	invalidateView(chart)
	queryHistoryData()

class AppDelegate(NSObject):
	def windowWillClose_(self, notification):
		os._exit(0)
	def applicationDidFinishLaunching_(self, notification):
		gPaint.size = FCSize(900, 770)
		window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer_(
		NSMakeRect(0, 0, gPaint.size.cx, gPaint.size.cy),
		15,
		NSBackingStoreBuffered,
		False
		)
		window.setDelegate_(self)
		window.orderFrontRegardless()
		view = FCUIView.alloc().initWithFrame_(NSMakeRect(0, 0, gPaint.size.cx, gPaint.size.cy))
		view.paint = gPaint
		window.setContentView_(view)
		gPaint.view = view
		loadUI()

app = NSApplication.sharedApplication()
delegate = AppDelegate.alloc().init()
app.setDelegate_(delegate)
app.run()
